<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import file from '@/assets/file';

import { showToast } from 'vant';

const emit = defineEmits<{ (e: 'success'): void; (e: 'close'): void }>();

const polyfill = 9 as number; // 补偿值

let index = 0; // 资源索引

let initial = 0; // 初始位置

let isMove = false;

let isTouch = false;

const key = ref(0);

const loading = ref(false);

const originRef = ref<HTMLElement>(); // 底图

const trackRef = ref<HTMLElement>(); // 滑轨

const blockRef = ref<HTMLElement>(); // 滑块

const source = ref<Array<string | number>>([]); // 资源

const offset = ref(0); // 偏移量

/**
 * 获取资源
 */
const getSource = () => {
  const result = file[index];
  source.value = result.map((item, index) => {
    if (index !== 2) {
      return `data:image/png;base64,${item}`;
    } else {
      return item;
    }
  });

  if (index === 2) {
    index = 0;
  } else {
    index += 1;
  }
};

/**
 * 初始化
 */
const init = async () => {
  reset();
  await getSource();
};

/**
 * 重置
 */
const reset = () => {
  isMove = false;
  isTouch = false;
  offset.value = polyfill;
};

/**
 * 按下
 */
const handleDown = (event: TouchEvent) => {
  isTouch = true;
  initial = Math.floor(
    event.touches[0].pageX - trackRef.value!.getBoundingClientRect().left
  );
};

/**
 * 移动
 */
const handleMove = (event: TouchEvent) => {
  if (isTouch === false) {
    return;
  }

  const _offset =
    Math.floor(
      event.touches[0].pageX - trackRef.value!.getBoundingClientRect().left
    ) - initial;

  const trackWidth = Number(
    trackRef.value!.getBoundingClientRect().width.toFixed(2)
  );

  const blockWidth = Number(
    blockRef.value!.getBoundingClientRect().width.toFixed(2)
  );

  const offsetRange = [polyfill, trackWidth - blockWidth + polyfill];

  if (offsetRange[0] <= _offset && _offset <= offsetRange[1]) {
    isMove = true;
    offset.value = _offset;
  }
};

/**
 * 松开
 */
const handleUp = async () => {
  if (isTouch === false || isMove === false) {
    return;
  }

  const target = source.value[2] as number;

  const ratio = Number(
    (
      offset.value / Number(originRef.value!.getBoundingClientRect().width)
    ).toFixed(2)
  );

  const ratioRange = [target - 0.02, target + 0.02];

  if (ratioRange[0] <= ratio && ratio <= ratioRange[1]) {
    showToast('验证成功');
    emit('success');
  } else {
    showToast('验证失败');
  }

  handleRefresh();
};

/**
 * 刷新
 */
const handleRefresh = async () => {
  reset();

  await getSource();

  key.value++;
};

/**
 * 关闭
 */
const handleClose = () => {
  emit('close');
};

onMounted(async () => {
  loading.value = true;

  await init();

  loading.value = false;
});
</script>

<template>
  <van-overlay class="component" v-bind="$attrs">
    <div class="component__region component__status--layout1">
      <div class="component__row component__status--layout2">
        <div class="component__text--title1">请完成安全验证</div>

        <img
          class="component__button--action1"
          src="@/assets/image/25303@2x.png"
          @click="() => handleClose()"
        />
      </div>

      <div
        class="component__block component__status--layout3"
        v-if="!loading"
        :key="key"
      >
        <div class="component__status--layout4" ref="originRef">
          <img class="component__icon--badge1" :src="source[0] as string" />
        </div>

        <div class="component__status--layout6" ref="trackRef">
          <div
            class="component__status--layout5"
            :style="{ left: `${offset}px` }"
          >
            <img class="component__icon--badge2" :src="source[1] as string" />
          </div>

          <img
            class="component__icon--badge3"
            :style="{ left: `${offset}px` }"
            ref="blockRef"
            src="@/assets/image/25302@2x.png"
            @touchstart="($event) => handleDown($event)"
            @touchmove="($event) => handleMove($event)"
            @touchend="() => handleUp()"
          />

          <div class="component__text--describe1">向右拖动滑块填充拼图</div>
        </div>

        <img
          class="component__button--action2"
          src="@/assets/image/25304@2x.png"
          @click="() => handleRefresh()"
        />
      </div>

      <van-loading
        class="component__status--layout7"
        v-else
        size="24px"
        vertical
      >
        加载中...
      </van-loading>
    </div>
  </van-overlay>
</template>

<style lang="scss" scoped>
.component {
  &__text {
    &--title1 {
      font-weight: 400;
      font-size: 16px;
      color: #333333;
    }

    &--describe1 {
      font-weight: 400;
      font-size: 14px;
      color: #bebebe;
    }
  }

  &__icon {
    &--badge1 {
      width: 252px;
      height: 135px;
      border-radius: 3px;
    }

    &--badge2 {
      height: 135px;
    }

    &--badge3 {
      position: absolute;
      bottom: 1px;

      display: flex;
      justify-content: center;
      align-items: center;

      width: 40px;
      height: 38px;
      user-select: none;
      transition: background 0.2s linear;
    }
  }

  &__button {
    &--action1 {
      width: 24px;
      height: 24px;
    }

    &--action2 {
      position: absolute;
      top: 12px;
      right: 18px;

      width: 22px;
      height: 22px;
    }
  }

  &__status {
    &--layout1 {
      position: absolute;
      top: 49%;
      left: 50%;
      transform: translate(-50%, -50%);

      padding: 16px;
      width: 300px;
      min-height: 200px;
      background-color: #ffffff;
      border-radius: 8px 8px 8px 8px;
    }

    &--layout2 {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    &--layout3 {
      position: relative;

      display: flex;
      flex-direction: column;
      align-items: center;

      margin-top: 10px;
    }

    &--layout4 {
      overflow: hidden;
      width: 252px;
      border-radius: 8px 8px 8px 8px;
    }

    &--layout5 {
      position: absolute;
      top: 0;
    }

    &--layout6 {
      overflow: hidden;
      margin: auto;
      margin-top: 22px;
      width: 252px;
      height: 40px;
      line-height: 40px;
      text-align: center;
      background-color: #f8f4fc;
      border: 1px solid #e6e6e6;
      border-radius: 8px 8px 8px 8px;
    }

    &--layout7 {
      margin-top: 50px;
    }
  }
}
</style>
